home *** CD-ROM | disk | FTP | other *** search
- /* © 1988-91, Bowers Development Corp. */
- /* Cursors.c */
-
- #include <Types.h>
- #include <Quickdraw.h>
- #include <Controls.h>
- #include <Dialogs.h>
- #include <Events.h>
- #include <Lists.h>
- #include <Menus.h>
- #include <Resources.h>
- #include "Globals.h" /* for inBackground, curEvent, curWindow, cur, etc. */
-
- #include "Cursors.h"
-
- #include <ToolUtils.h> /* for GetCursor, HiWord */
-
- #pragma segment Cursors
-
- RgnHandle cursorRgn;
- CursHandle watch;
-
- #define kSpinTicks 15 /*1/4 of a second*/
- #define topLeft(r) (((Point *) &(r))[0])
- #define botRight(r) (((Point *) &(r))[1])
-
- typedef struct
- {
- struct
- {
- unsigned short isColor : 1; /*TRUE ===> using color cursors (high bit)*/
- unsigned short count : 15; /*# of cursors or “frames” in the cursor list (0-15th bits)*/
- } info;
- short frame; /*cursor list index of the next cursor frame (0-based)*/
- CursHandle hCursors [1]; /*Variable-sized list of cursor handles (0-based index)*/
- } AnimCursRec, *AnimCursPtr, **AnimCursHnd;
-
- static CursHandle iBeam;
- static AnimCursHnd shAnimCurs; /*=> Animated cursor list*/
- static long sLastTick; /*TickCount of last SetCursor call*/
-
- /*----------*/
- void LoadCursors ()
- {
- watch = GetCursor (watchCursor);
- iBeam = GetCursor (iBeamCursor);
-
- cursorRgn = NewRgn ();
-
- InitCursor ();
- } /*LoadCursors*/
-
- /*----------*/
- static void GlobalRectRgn (RgnHandle destRegion,
- Rect sourceRect);
- static void GlobalRectRgn (RgnHandle destRegion,
- Rect sourceRect)
- {
- LocalToGlobal (&topLeft (sourceRect));
- LocalToGlobal (&botRight (sourceRect));
- RectRgn (destRegion, &sourceRect);
- } /*GlobalRectRgn*/
-
- /*----------*/
- void ShapeCursor ()
- {
- WindowPtr front;
- WindowPeek frontPeek;
- Point mousePoint;
- RgnHandle arrowRgn;
- RgnHandle iBeamRgn;
- Rect textRect;
- RgnHandle contentRgn;
- RgnHandle scrollBarRgn;
- Rect scrollBarRect;
-
- front = FrontWindow ();
- frontPeek = (WindowPeek) front;
- if (inBackground) {
- /*let foreground set cursor*/
- } else if ((front != NULL) && (frontPeek->windowKind < 0)) {
- /*let da set its own cursor*/
- } else {
- arrowRgn = NewRgn ();
- iBeamRgn = NewRgn ();
- contentRgn = NewRgn ();
- scrollBarRgn = NewRgn ();
- RectRgn (arrowRgn, &qd.screenBits.bounds);
- mousePoint = curEvent.where;
- if (front == NULL) {
- /*arrow*/
- } else if (front == curWindow) {
- SetPort (curWindow); /*for local-to-global*/
- GlobalRectRgn (contentRgn, qd.thePort->portRect);
- if (cur->vScroll != NULL) {
- scrollBarRect = (**(cur->vScroll)).contrlRect;
- GlobalRectRgn (scrollBarRgn, scrollBarRect);
- DiffRgn (contentRgn, scrollBarRgn, contentRgn);
- }
- if (cur->hScroll != NULL) {
- scrollBarRect = (**(cur->hScroll)).contrlRect;
- GlobalRectRgn (scrollBarRgn, scrollBarRect);
- DiffRgn (contentRgn, scrollBarRgn, contentRgn);
- }
- if (cur->text != NULL) {
- textRect = (**(cur->text)).viewRect;
- GlobalRectRgn (iBeamRgn, textRect);
- SectRgn (iBeamRgn, contentRgn, iBeamRgn);
- }
- DiffRgn (arrowRgn, iBeamRgn, arrowRgn);
- }
- if (PtInRgn (mousePoint, iBeamRgn)) {
- SetCursor (&(**iBeam));
- CopyRgn (iBeamRgn, cursorRgn);
- } else {
- SetCursor (&qd.arrow);
- CopyRgn (arrowRgn, cursorRgn);
- }
- DisposeRgn (arrowRgn);
- DisposeRgn (iBeamRgn);
- DisposeRgn (contentRgn);
- DisposeRgn (scrollBarRgn);
- }
- } /*ShapeCursor*/
-
- /*----------*/
- /* This procedure sets up this unit so that later calls to SpinCursor will spin */
- /* the 'acur' resource with id aCurID. You MUST call StartBusyCursor before calling */
- /* SpinCursor, SpinBackwards, or StopBusyCursor. */
- /*----------*/
- void StartBusyCursor (short aCurID)
- {
- short cursID; /*==> One cursor's rsrc id in shAnimCurs*/
- CursHandle hCurs; /*==> One cursor in shAnimCurs*/
- unsigned short i; /*index into animated cursor list*/
- Boolean isColor; /*TRUE if cursor list has color cursors, FALSE otherwise*/
-
- shAnimCurs = (AnimCursHnd) GetResource ('acur', aCurID);
- if (shAnimCurs != NULL) {
- HNoPurge ((Handle) shAnimCurs); /*We need to make shAnimCurs non-purgeable for its life span*/
- isColor = (**shAnimCurs).info.isColor;
- /* The cursor list is a list of CursHandles, but in the resource file the cursor list is a list */
- /* of resource IDs in the upper 16 bits of the CursHandles. */
- for (i = 0; i < (**shAnimCurs).info.count; i++) {
- cursID = (short) HiWord ( (long) (**shAnimCurs).hCursors [i]);
- if (isColor) {
- hCurs = (CursHandle) GetCCursor (cursID);
- } else {
- hCurs = GetCursor (cursID);
- }
- (**shAnimCurs).hCursors [i] = hCurs; /*Replace the resource IDs with CursHandles*/
- /* If the cursor is a non-color cursor ('curS' resource); make it non-purgeable. GetCColor */
- /* returns copies of the 'crsr' resources so they are already non-purgeable. */
- if ((!isColor) && (hCurs != NULL)) {
- HNoPurge ((Handle) hCurs);
- }
- } /*for*/
- } /*otherwise, shAnimCurs == NULL, resource not found*/
-
- sLastTick = 0;
- } /*StartBusyCursor*/
-
- /*----------*/
- /* This private procedure spins the cursor by frameInc if more than kSpinTicks ticks have gone
- | by since it last changed the cursor.
- */
- /*----------*/
- static void SpinFrame(short frameInc);
- static void SpinFrame(short frameInc)
- {
- short count; /*count of animated cursors*/
- short frameNum; /*index into animated cursor list*/
- CursHandle hCurs; /*==> One cursor in shAnimCurs*/
- long ticks;
-
- if (shAnimCurs != NULL) {
- ticks = TickCount ();
- if ((ticks - sLastTick) > kSpinTicks) {
- count = (**shAnimCurs).info.count;
- /* Enough time has elapsed since last cursor change, so change the cursor, bump the */
- /* frame count and note the ticks for next time. */
- frameNum = (**shAnimCurs).frame % count;
- hCurs = (**shAnimCurs).hCursors [frameNum];
- if (hCurs != NULL) {
- if ((**shAnimCurs).info.isColor) {
- SetCCursor ((CCrsrHandle) hCurs);
- } else {
- HLock ((Handle) hCurs);
- SetCursor (&(**hCurs));
- HUnlock ((Handle) hCurs);
- }
- } /*otherwise, hCurs == NULL*/
-
- (**shAnimCurs).frame = (frameNum + count + frameInc) % count;
- /* if (frameInc < 0,) frameNum + frameInc */
- /* may be < 0, so (frameNum + frameInc) % count */
- /* would also be < 0. */
- /* Using frameNum + count + frameInc makes this */
- /* less likely to happen. */
- sLastTick = ticks;
- } /*otherwise, not enough time has elapsed to change the cursor*/
- } /*otherwise, shAnimCurs == NULL*/
- } /*SpinFrame*/
-
- /*----------*/
- /* This procedure should be called as often as possible when the cursor is supposed to spin. */
- /* It will spin the cursor forward one frame if more than kSpinTicks ticks have gone by since */
- /* it last changed the cursor. */
- /*----------*/
- void SpinCursor (void)
- {
- SpinFrame (1 /*frameInc*/);
- } /*SpinCursor*/
-
- /*----------*/
- /* This procedure should be called as often as possible when the cursor is supposed to spin. */
- /* It will spin the cursor backward one frame if more than kSpinTicks ticks have gone by since */
- /* it last changed the cursor. */
- /*----------*/
- void SpinBackwards (void)
- {
- SpinFrame (-1 /*frameInc*/);
- } /*SpinBackwards*/
-
- /*----------*/
- /* This procedure does the opposite of StartBusyCursor, that is, it disposes of the spinning */
- /* cursor allocated by StartBusyCursor, and sets the cursor to the standard arrow. */
- /*----------*/
- void StopBusyCursor (void)
- { CursHandle hCurs; /*==> One cursor in shAnimCurs*/
- unsigned short i; /*index into animated cursor list*/
- Boolean isColor; /*TRUE if cursor list has color cursors, FALSE otherwise*/
-
- if (shAnimCurs != NULL) {
- /*Dispose shAnimCurs's handles*/
- isColor = (**shAnimCurs).info.isColor;
- for (i = 0; i < (**shAnimCurs).info.count; i++) {
- hCurs = (**shAnimCurs).hCursors [i];
- if (hCurs != NULL) {
- if (isColor) {
- DisposCCursor ((CCrsrHandle) hCurs);
- } else {
- HPurge ((Handle) hCurs);
- }
- } /*otherwise, hCurs == NULL*/
- } /*otherwise, not enough time has elapsed to change the cursor*/
-
- ReleaseResource ((Handle) shAnimCurs);
- shAnimCurs = NULL;
- sLastTick = 0;
- } /*otherwise, shAnimCurs == NULL*/
- InitCursor ();
- } /*StopBusyCursor*/
-